#ifdef _DBLIST_

#include "structure.h"
#include "MC.h"
#include "model_Stream_IO.h"

#define NUM(x)  ((_ptlong)((x)->mark))
template<_ptlong areaspare>
class autoList
{
 public:
  autoList(_ptlong* (*_alloc)(_ptlong),_ptlong _areanum)
    {
      //  alloc = _alloc;
      areanum = _areanum;
      nodes = _alloc(sizeof(listnode<1> * _areanum));
      for(_ptlong i = 0; i < _areanum ;i ++)
	{
	  MakeListNode(&(nodes[i]),areaspare);
	  if(i != 0)
	    InsertListNode(&(node[i - 1]),&(node[i]));
	}
      head = &(node[0]);
      tail = &(node[_areanum - 1]);
    }
  inline _ptlong PopArea(_ptlong area = (~0))
  {   
    listnode<1>* popone = (area == (~0)
			   ? head
			   : &(node[area]) );
    popone->mark = (void*)(NUM(popone) - 1);
    ReplaceNode(popone);
    while(head->pre != NULL)
      head = head->pre;
    return ((((_ptlong)popone) - ((_ptlong)nodes))/sizeof(listnode<1>*));
  }

  inline int PushArea(_ptlong offset)
  {
    listnode<1>* pushone = &(nodes[offset]);
    pushone->mark = (void*)(NUM(popone) + 1);
    ReplaceNode(pushone);
    while(tail->next != NULL)
      tail = tail->next;
    
  }
  static void ReplaceNode(listnode<1>* node)
  {
    if(node->next != NULL && NUM(node) < NUM(node->next))
      {
	listnode<1>* nextnode = node->next;
	ReplaceNode((RemoveListNode(node),InsertListNode(nextnode,node),node));
      }
    else if(node->pre != NULL && NUM(node) > NUM(node->pre))
      {
	listnode<1>* prenode = node->pre;
	ReplaceNode((RemovelistNode(node),InsertListNode(prenode->pre,node),node));
      }
  }
  
 private:
  //  _ptlong* (*alloc)(_ptlong);
  _ptlong areanum;
  _ptlong areaspare;
  listnode<1>* nodes;
  listnode<1>* head;
  listnode<1>* tail;
}
template<_ptlong areablocks>
class streamReg
{
 public:
  StreamReg(void (*CleanUp)(_ptlong*,_ptlong))
    {
      CleanUp(reg,sizeof(reg));
    }
  _ptlong PopRegOffset()
  {
    for(_ptlong i = 0 ; i < areablocks ; i++)
      {
	if(!(reg[i] & IS_INUSE))
	  {
	    reg[i] |= IS_INUSE;
	    return i;
	  }
      }
  }
  int PushRegOffset(_ptlong offset)
  {
    if(reg[i] & IS_INUSE)
      {
	reg[i] &= ~IS_INUSE;
	return 1;
      }
    return 0;
  }

  // private:
  //  constexpr _ptlong _ptlongbytes = areablocks / (sizeof(_ptlong) * 8); //per bits symblize a stream block
  _ptlong reg[areablocks];
   
}

#endif
